from datetime import datetime

from werkzeug.security import generate_password_hash, check_password_hash
from faker import Faker

from . import db


class User(db.Model):
    """用户模型类"""
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True, doc='用户id')
    email = db.Column(db.String(64), unique=True, index=True, doc='用户邮箱')
    username = db.Column(db.String(64), unique=True, index=True, doc='用户名')
    password_hash = db.Column(db.String(128), doc='密码')
    member_since = db.Column(db.DateTime(), default=datetime.utcnow, doc='注册时间')
    last_seen = db.Column(db.DateTime(), default=datetime.utcnow, doc='最后登录时间')
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'), doc='用户所在用户组id')
    rd_coins = db.Column(db.Integer, default=0, doc='瑞典币')
    avatar = db.Column(db.String(256),
                       default='http://q1998r88n.bkt.clouddn.com/FlPkS4f_nqrpuP-rIPme1L7M6e5w', doc='用户头像')

    @property
    def password(self):
        """读取password属性时调用"""
        raise AttributeError('不可以读取密码属性！')

    @password.setter
    def password(self, password):
        """设置password属性时调用"""
        self.password_hash = generate_password_hash(password)

    def verify_password(self, password):
        """校验密码是否正确，返回True或False"""
        return check_password_hash(self.password_hash, password)

    @classmethod
    def _init_users(cls):
        """初始化用户表"""
        admin = cls(
            username='admin',
            password='admin',
            email='chenyige3@gmail.com',
            rd_coins=9999,
            avatar='http://q1998r88n.bkt.clouddn.com/FlPkS4f_nqrpuP-rIPme1L7M6e5w',
            role=Role.query.filter_by(name='站长').first()
        )
        db.session.add_all([admin])
        db.session.commit()


class Role(db.Model):
    """用户组模型类"""

    class Permissions(object):
        """权限与数字映射关系"""
        MAPPING = {
            'BACKGROUND': 1,  # 操作网站后台
            'READ_LV1': 2,  # 初级阅读权限
            'READ_LV2': 4  # 高级阅读权限
        }

    __tablename__ = 'roles'
    id = db.Column(db.Integer, primary_key=True, doc='用户组id')
    name = db.Column(db.String(32), doc='用户组名称')
    default = db.Column(db.Boolean, default=False, doc='是否为新建用户的默认用户组')
    permissions = db.Column(db.Integer, doc='用户组权限值')
    users = db.relationship('User', backref='role', lazy='dynamic', doc='该用户组对应的用户')

    def has_permission(self, permission_str):
        """判断用户组是否拥有某权限"""
        # 从权限映射表中获取权限数字
        permission_int = self.Permissions.MAPPING.get(permission_str)
        # 使用位与运算来判断，拥有该权限返回True，没有则返回False
        return self.permissions & permission_int == permission_int

    @classmethod
    def all_roles_with_permission(cls, permission_str):
        """查询拥有某权限的所有用户组"""
        roles = cls.query.all()
        # result是包含拥有该权限的所有用户组的列表
        result = [role for role in roles if role.has_permission(permission_str)]
        # count是拥有该权限的用户组的数量
        count = len(result) if result else 0
        return result, count

    @classmethod
    def _init_roles(cls):
        """初始化用户组表"""
        admin = cls(name='站长', permissions=7)
        unconfirmed = cls(name='未认证用户', permissions=0, default=True)
        lv1 = cls(name='萌新', permissions=2)
        db.session.add_all([admin, unconfirmed, lv1])
        db.session.commit()


class Article(db.Model):
    """文章模型类"""
    __tablename__ = 'articles'
    id = db.Column(db.Integer, primary_key=True, doc='文章id')
    title = db.Column(db.String(128), doc='文章标题')
    author = db.Column(db.String(64), unique=True, doc='作者姓名')
    body = db.Column(db.Text, doc='文章内容')
    create_time = db.Column(db.DateTime(), doc='创建时间')

# def add_data(count=20):
#     fake = Faker()
#     for i in range(count):
#         A = Article(title=fake.)
